package com.auth.manager.security;

import com.auth.manager.security.auth.AuthDeniedHandler;
import com.auth.manager.security.auth.JwtAuthFilter;
import com.auth.manager.security.config.WhiteUrlConfig;
import com.auth.manager.security.login.LoginAuthenticationFilter;
import com.auth.manager.security.login.NotLoginEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.config.http.SessionCreationPolicy;

import java.util.List;

/**
 * @version 1.0.0
 * @Date: 2022/4/26 18:45
 * @Author ZhuYouBin
 * @Description Security配置类
 */
@Configuration // 指定当前类为配置类
@EnableWebSecurity // 开启security
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 用户未登录异常处理
     */
    @Autowired
    private NotLoginEntryPoint notLoginEntryPoint;
    /**
     * 用户权限不足异常处理
     */
    @Autowired
    private AuthDeniedHandler authDeniedHandler;
    /**
     * Jwt认证授权过滤器
     */
    @Autowired
    private JwtAuthFilter jwtAuthFilter;

    // 用户认证相关设置[登录认证]
    // 这里没用到,这个方法可以不重写
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    }

    // 用户授权相关设置[权限控制]
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 登录表单[前后端分离模式下,表单不需要配置]

        // 获取白名单
        List<String> whiteUrlLists = WhiteUrlConfig.getWhiteUrl();

        // 权限控制
        // [过滤器将所有请求路径拦截,需要认证后才能够访问]
        http.authorizeHttpRequests()
                // 白名单处理
                .antMatchers(whiteUrlLists.toArray(new String[0])).permitAll()
                // 所有请求url都需要认证才能访问
                .anyRequest().authenticated();

        // 过滤器[自定义的过滤器]
        http.addFilterBefore(jwtAuthFilter, LoginAuthenticationFilter.class);

        // 异常处理[自定义认证授权异常处理]
        http.exceptionHandling()
                .authenticationEntryPoint(notLoginEntryPoint) // 未登录时候异常处理
                .accessDeniedHandler(authDeniedHandler); // 授权失败异常处理

        // 禁用session,前后端分离模式下,不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // 关闭CSRF
        http.csrf().disable();
        // 开启Spring Security 的跨域
        http.cors();
    }

    // 静态资源访问权限设置[静态资源]
    // 前后端分离模式下,这个方法可以不重写
    @Override
    public void configure(WebSecurity web) throws Exception {
    }

    // 密码加密器
    @Bean // 注入到IOC容器里面
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
